/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import javax.sip.InvalidArgumentException;
import javax.sip.header.RAckHeader;
import java.text.ParseException;

/**
 * This interface represents the RAck header, as defined by
 * <a href = "http://www.ietf.org/rfc/rfc3262.txt">RFC3262</a>, this
 * header is not part of RFC3261.
 * <p/>
 * The PRACK messages contain an RAck header field, which indicates the
 * sequence number of the provisional response that is being acknowledged (each
 * provisional response is given a sequence number, carried in the RSeq header
 * field in the Provisional response). The acknowledgements are not cumulative,
 * and the specifications recommend a single outstanding provisional response at
 * a time, for purposes of congestion control.
 * <p/>
 * The RAck header contains two numbers and a method tag. The first number is
 * the sequence number from the RSeqHeader in the provisional response that is
 * being acknowledged. The next number is the sequence number that is copied
 * from the CSeqHeader along with the method tag, from the response that is being
 * acknowledged.
 * <p/>
 * For Example:<br>
 * <code>RAck: 776656 1 INVITE</code>
 * <p/>
 * A server must ignore Headers that it does not understand. A proxy must not
 * remove or modify Headers that it does not understand.
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class RAckHeaderImpl extends HeaderBase implements RAckHeader {
    private final static RAckHeaderParser parser = new RAckHeaderParser();

    private Integer rSeqNumber;
    private Integer cSeqNumber;
    private String method;

    public RAckHeaderImpl() {
        super(RAckHeader.NAME);
    }

    RAckHeaderImpl(byte[] data, int start, int end) {
        super(RAckHeader.NAME, data, start, end);
    }

    public Object clone() {
        final RAckHeaderImpl header = new RAckHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.rSeqNumber = this.rSeqNumber;
            header.cSeqNumber = this.cSeqNumber;
            header.method = this.method;
        }
        return header;
    }

    protected HeaderParser getParser() {
        return parser;
    }

    protected String getValueAsString() {
        return Integer.toString(rSeqNumber) + ' ' + Integer.toString(cSeqNumber) + ' ' + method;
    }

    /**
     * Sets the method of RAckHeader, which correlates to the method of the
     * CSeqHeader of the provisional response being acknowledged.
     *
     * @param method the new string value of the method of the RAckHeader
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the method value.
     */
    public void setMethod(String method) throws ParseException {
        parse();
        this.method = method;
        invalidateHeaderData();
    }

    /**
     * Gets the method of RAckHeader.
     *
     * @return method of RAckHeader.
     */
    public String getMethod() {
        parse();
        return this.method;
    }

    /**
     * Sets the sequence number value of the CSeqHeader of the provisional
     * response being acknowledged. The sequence number MUST be expressible as
     * a 32-bit unsigned integer and MUST be less than 2**31.
     *
     * @param cSeqNumber the new cSeq number of this RAckHeader.
     * @throws javax.sip.InvalidArgumentException
     *          if supplied value is less than zero.
     */
    public void setCSeqNumber(int cSeqNumber) throws InvalidArgumentException {
        parse();
        this.cSeqNumber = cSeqNumber;
        invalidateHeaderData();
    }

    /**
     * Gets the CSeq sequence number of this RAckHeader.
     *
     * @return the integer value of the cSeq number of the RAckHeader.
     */
    public int getCSeqNumber() {
        parse();
        return this.cSeqNumber;
    }

    /**
     * Sets the sequence number value of the RSeqHeader of the provisional
     * response being acknowledged. The sequence number MUST be expressible as
     * a 32-bit unsigned integer and MUST be less than 2**31.
     *
     * @param rSeqNumber the new rSeq number of this RAckHeader.
     * @throws javax.sip.InvalidArgumentException
     *          if supplied value is less than zero.
     */
    public void setRSeqNumber(int rSeqNumber) throws InvalidArgumentException {
        parse();
        this.rSeqNumber = rSeqNumber;
        invalidateHeaderData();
    }

    /**
     * Gets the RSeq sequence number of this RAckHeader.
     *
     * @return the integer value of the RSeq number of the RAckHeader.
     */
    public int getRSeqNumber() {
        parse();
        return this.rSeqNumber;
    }
}
/*
 * $Log$
 */